#
# Copyright (c) 2021 Tero Hänninen.
#

.PHONY: clean-all clean clean-s1 clean-s2 clean-s3 clean-test-s1 clean-test-s2 clean-unittest-s2 clean-unittest-s1

# The lowercase variables below are meant for cmdline manipulation.

gnc0 = gnc0
cxx = g++
cxxflags = -ansi -Wall -c -O3
gncflags = -release -O2

BINDIR = .
LIBDIR = .
OBJDIR = obj

STD_S1_OBJDIR = $(OBJDIR)/std-s1
STD_S2_OBJDIR = $(OBJDIR)/std-s2
STD_S3_OBJDIR = $(OBJDIR)/std-s3
GNC_S1_OBJDIR = $(OBJDIR)/gnc-s1
GNC_S2_OBJDIR = $(OBJDIR)/gnc-s2
GNC_S3_OBJDIR = $(OBJDIR)/gnc-s3
TEST_S1_OBJDIR = $(OBJDIR)/test-s1
TEST_S2_OBJDIR = $(OBJDIR)/test-s2
UNITTEST_S1_OBJDIR = $(OBJDIR)/ut-s1
UNITTEST_S2_OBJDIR = $(OBJDIR)/ut-s2

LIB_STD_S1 = $(LIBDIR)/libgordon-s1.a
LIB_STD_S2 = $(LIBDIR)/libgordon-s2.a
LIB_STD_S3 = $(LIBDIR)/libgordon-s3.a
LIB_LLVM_BRIDGE = $(OBJDIR)/llvm_bridge.a
GNC_LIB_S1 = $(OBJDIR)/gnc-s1.a
GNC_LIB_S2 = $(OBJDIR)/gnc-s2.a
GNC_LIB_S3 = $(OBJDIR)/gnc-s3.a
GNC_BIN_S1 = $(BINDIR)/gnc-s1
GNC_BIN_S2 = $(BINDIR)/gnc-s2
GNC_BIN_S3 = $(BINDIR)/gnc-s3
TEST_GNC_S1 = $(BINDIR)/test-s1
TEST_GNC_S2 = $(BINDIR)/test-s2
UNITTEST_S1 = $(BINDIR)/ut-s1
UNITTEST_S2 = $(BINDIR)/ut-s2
UNITTEST_LIB_S1 = $(OBJDIR)/ut-s1.a
UNITTEST_LIB_S2 = $(OBJDIR)/ut-s2.a
UNITTEST_STD_S1 = $(LIBDIR)/libgordon-ut-s1.a
UNITTEST_STD_S2 = $(LIBDIR)/libgordon-ut-s2.a

LLVM_CONFIG_COMMAND = "llvm-config-10"
LLVM_CXX_FLAGS = `$(LLVM_CONFIG_COMMAND) --cxxflags`
LLVM_LINK_FLAGS = `$(LLVM_CONFIG_COMMAND) --ldflags --libs`

LLVM_BRIDGE_SOURCES = gnc/llvm_bridge.cpp

GNC_ROOT = gnc/gnc.i

GNC_SOURCES = \
	gnc/gnc.i \
	gnc/abi.gor \
	gnc/ast.gor \
	gnc/astdump.gor \
	gnc/astfree.gor \
	gnc/bbqueue.gor \
	gnc/config.gor \
	gnc/console.gor \
	gnc/debugprint.gor \
	gnc/drive.gor \
	gnc/dyna.gor \
	gnc/errors.gor \
	gnc/global.gor \
	gnc/lex.gor \
	gnc/llvm.gor \
	gnc/llvmffi.gor \
	gnc/mangle.gor \
	gnc/mir.gor \
	gnc/mirexp.gor \
	gnc/mirgen.gor \
	gnc/mirvm.gor \
	gnc/monopool.gor \
	gnc/parse.gor \
	gnc/peekbuf.gor \
	gnc/platform.gor \
	gnc/pool.gor \
	gnc/printcrutch.gor \
	gnc/semantic.gor \
	gnc/semexp.gor \
	gnc/setups.gor \
	gnc/stash.gor \
	gnc/strutil.gor \
	gnc/symtab.gor \
	gnc/sys/sys.i \
	gnc/sys/unix/unix.i \
	gnc/sys/unix/linux/linux.i \
	gnc/sys/unix/linux/gnu_x86_64.gor \
	gnc/system/system.i \
	gnc/system/linux.gor \
	gnc/system/windows.gor \
	gnc/test.gor \
	gnc/tokens.gor \
	gnc/type.gor \
	gnc/typeinfo.gor \
	gnc/typeinfomap.gor \
	gnc/xxhash.gor

STD_ROOT = std/std.i

STD_SOURCES = \
	std/std.i \
	std/dyna.gor \
	std/failure.gor \
	std/io.gor \
	std/syscore/syscore.i \
	std/syscore/unix/unix.i \
	std/syscore/unix/linux/linux.i \
	std/syscore/unix/linux/gnu_x86_64.gor \
	std/mem.gor \
	std/typeinfo.gor

TEST_ROOT = test/test.i

TEST_SOURCES = \
	test/aggs.gor \
	test/blocks.gor \
	test/casts.gor \
	test/cte.gor \
	test/enums.gor \
	test/functions.gor \
	test/globals.gor \
	test/impa.gor \
	test/impb.gor \
	test/impc.gor \
	test/impd.gor \
	test/labels.gor \
	test/macros_aux.gor \
	test/macros.gor \
	test/numeric.gor \
	test/scopestmt.gor \
	test/test.i \
	test/typeexpr.gor \
	test/typeinfo.gor \
	test/util.gor \
	test/vararg.gor

$(UNITTEST_S2): $(UNITTEST_STD_S2) $(UNITTEST_LIB_S2) $(LIB_LLVM_BRIDGE)
	gcc -lstdc++ $(UNITTEST_LIB_S2) $(UNITTEST_STD_S2) -lm $(LIB_LLVM_BRIDGE) $(LLVM_LINK_FLAGS) -o $(UNITTEST_S2)
	$(UNITTEST_S2)

$(UNITTEST_S1): $(UNITTEST_STD_S1) $(UNITTEST_LIB_S1) $(LIB_LLVM_BRIDGE)
	gcc -lstdc++ $(UNITTEST_LIB_S1) $(UNITTEST_STD_S1) -lm $(LIB_LLVM_BRIDGE) $(LLVM_LINK_FLAGS) -o $(UNITTEST_S1)
	$(UNITTEST_S1)

$(UNITTEST_LIB_S2): $(GNC_BIN_S1) $(GNC_SOURCES)
	$(GNC_BIN_S1) $(GNC_ROOT) $(gncflags) -std $(STD_ROOT) -d $(UNITTEST_S2_OBJDIR) -define unittest -v -c -lib -o $(UNITTEST_LIB_S2)

$(UNITTEST_LIB_S1): $(GNC_SOURCES)
	$(gnc0) $(GNC_ROOT) $(gncflags) -std $(STD_ROOT) -d $(UNITTEST_S1_OBJDIR) -define unittest -v -c -lib -o $(UNITTEST_LIB_S1)

$(TEST_GNC_S2): $(GNC_BIN_S2) $(TEST_SOURCES)
	$(GNC_BIN_S2) $(TEST_ROOT) -std $(STD_ROOT) $(LIB_STD_S2) -d $(TEST_S2_OBJDIR) -o $(TEST_GNC_S2)
	$(TEST_GNC_S2)
	@echo "Success."

$(TEST_GNC_S1): $(GNC_BIN_S1) $(TEST_SOURCES)
	$(GNC_BIN_S1) $(TEST_ROOT) -std $(STD_ROOT) $(LIB_STD_S1) -d $(TEST_S1_OBJDIR) -o $(TEST_GNC_S1)
	$(TEST_GNC_S1)
	@echo "Success."

$(GNC_BIN_S3): $(LIB_STD_S3) $(GNC_LIB_S3) $(LIB_LLVM_BRIDGE)
	gcc -lstdc++ $(GNC_LIB_S3) $(LIB_STD_S3) -lm $(LIB_LLVM_BRIDGE) $(LLVM_LINK_FLAGS) -o $(GNC_BIN_S3)

$(GNC_LIB_S3): $(GNC_BIN_S2)
	$(GNC_BIN_S2) $(GNC_ROOT) $(gncflags) -std $(STD_ROOT) -d $(GNC_S3_OBJDIR) -v -c -lib -o $(GNC_LIB_S3)

$(LIB_STD_S3): $(GNC_BIN_S2)
	$(GNC_BIN_S2) $(STD_ROOT) $(gncflags) -d $(STD_S3_OBJDIR) -v -c -lib -o $(LIB_STD_S3)

$(GNC_BIN_S2): $(LIB_STD_S2) $(GNC_LIB_S2) $(LIB_LLVM_BRIDGE)
	gcc -lstdc++ $(GNC_LIB_S2) $(LIB_STD_S2) -lm $(LIB_LLVM_BRIDGE) $(LLVM_LINK_FLAGS) -o $(GNC_BIN_S2)

$(GNC_LIB_S2): $(GNC_BIN_S1)
	$(GNC_BIN_S1) $(GNC_ROOT) $(gncflags) -std $(STD_ROOT) -d $(GNC_S2_OBJDIR) -v -c -lib -o $(GNC_LIB_S2)

$(LIB_STD_S2): $(GNC_BIN_S1)
	$(GNC_BIN_S1) $(STD_ROOT) $(gncflags) -d $(STD_S2_OBJDIR) -v -c -lib -o $(LIB_STD_S2)

$(GNC_BIN_S1): $(LIB_STD_S1) $(GNC_LIB_S1) $(LIB_LLVM_BRIDGE)
	gcc -lstdc++ $(GNC_LIB_S1) $(LIB_STD_S1) -lm $(LIB_LLVM_BRIDGE) $(LLVM_LINK_FLAGS) -o $(GNC_BIN_S1)

$(GNC_LIB_S1): $(GNC_SOURCES)
	$(gnc0) $(GNC_ROOT) $(gncflags) -std $(STD_ROOT) -d $(GNC_S1_OBJDIR) -v -c -lib -o $(GNC_LIB_S1)

$(LIB_STD_S1): $(STD_SOURCES)
	$(gnc0) $(STD_ROOT) $(gncflags) -d $(STD_S1_OBJDIR) -v -c -lib -o $(LIB_STD_S1)

$(UNITTEST_STD_S2): $(STD_SOURCES)
	$(gnc0) $(STD_ROOT) $(gncflags) -d $(UNITTEST_S2_OBJDIR) -v -c -lib -o $(UNITTEST_STD_S2)

$(UNITTEST_STD_S1): $(STD_SOURCES)
	$(gnc0) $(STD_ROOT) $(gncflags) -d $(UNITTEST_S1_OBJDIR) -v -c -lib -o $(UNITTEST_STD_S1)

$(LIB_LLVM_BRIDGE): $(OBJDIR)/llvm_bridge.o
	ar cqs $(LIB_LLVM_BRIDGE) $(OBJDIR)/llvm_bridge.o

$(OBJDIR)/llvm_bridge.o: $(LLVM_BRIDGE_SOURCES)
	mkdir -p $(OBJDIR)
	$(cxx) $(cxxflags) $(LLVM_BRIDGE_SOURCES) $(LLVM_CXX_FLAGS)
	mv *.o $(OBJDIR)/ 2>/dev/null || true

clean-all: clean
	rm $(GNC_BIN_S1) $(GNC_BIN_S2) $(GNC_BIN_S3) 2>/dev/null || true

clean: clean-s3
	rm -f $(OBJDIR)/*.o $(OBJDIR)/*.a
	rmdir $(OBJDIR) $(LIBDIR) 2>/dev/null || true

clean-s3: clean-s1 clean-s2
	rm -f $(STD_S3_OBJDIR)/*.o $(STD_S3_OBJDIR)/*.ll
	rm -f $(GNC_S3_OBJDIR)/*.o $(GNC_S3_OBJDIR)/*.ll
	rm -f $(LIB_STD_S3)
	rm -f $(GNC_LIB_S3)
	rmdir $(STD_S3_OBJDIR) $(GNC_S3_OBJDIR) 2>/dev/null || true

clean-s2: clean-s1 clean-test-s2
	rm -f $(STD_S2_OBJDIR)/*.o $(STD_S2_OBJDIR)/*.ll
	rm -f $(GNC_S2_OBJDIR)/*.o $(GNC_S2_OBJDIR)/*.ll
	rm -f $(LIB_STD_S2)
	rm -f $(GNC_LIB_S2)
	rmdir $(STD_S2_OBJDIR) $(GNC_S2_OBJDIR) 2>/dev/null || true

clean-test-s2:
	rm -f $(TEST_S2_OBJDIR)/*.o $(TEST_S2_OBJDIR)/*.ll
	rm -f $(TEST_GNC_S2)
	rmdir $(TEST_S2_OBJDIR) 2>/dev/null || true

clean-s1: clean-test-s1 clean-unittest-s2 clean-unittest-s1
	rm -f $(STD_S1_OBJDIR)/*.o $(STD_S1_OBJDIR)/*.ll
	rm -f $(GNC_S1_OBJDIR)/*.o $(GNC_S1_OBJDIR)/*.ll
	rm -f $(LIB_STD_S1)
	rm -f $(GNC_LIB_S1)
	rmdir $(STD_S1_OBJDIR) 2>/dev/null || true
	rmdir $(GNC_S1_OBJDIR) 2>/dev/null || true

clean-test-s1:
	rm -f $(TEST_S1_OBJDIR)/*.o $(TEST_S1_OBJDIR)/*.ll
	rm -f $(TEST_GNC_S1)
	rmdir $(TEST_S1_OBJDIR) 2>/dev/null || true

clean-unittest-s2:
	rm -f $(UNITTEST_S2_OBJDIR)/*.o $(UNITTEST_S2_OBJDIR)/*.ll
	rm -f $(UNITTEST_LIB_S2) $(UNITTEST_STD_S2)
	rm -f $(UNITTEST_S2)
	rmdir $(UNITTEST_S2_OBJDIR) 2>/dev/null || true

clean-unittest-s1:
	rm -f $(UNITTEST_S1_OBJDIR)/*.o $(UNITTEST_S1_OBJDIR)/*.ll
	rm -f $(UNITTEST_LIB_S1) $(UNITTEST_STD_S1)
	rm -f $(UNITTEST_S1)
	rmdir $(UNITTEST_S1_OBJDIR) 2>/dev/null || true
